#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>

#define EXIT_STR "quit"
#define MAX_INPUT_LEN 100

int main(int argc, char const *argv[])
{
    int pipeTest[2] = {0};
    int iRet = pipe( pipeTest );
    if( iRet == -1 )
    {
        perror( "fail pipe" );
        return -1;
    }

    pid_t pid = fork();
    if ( pid > 0 )               // 父进程, 从pipe读取字符串, 并打印
    {
        close( pipeTest[1] );
        char strReadPipe[MAX_INPUT_LEN];
        while ( 1 )
        {
            ssize_t iRetRead = read( pipeTest[0], strReadPipe, MAX_INPUT_LEN );
            if ( iRetRead == -1 )
            {
                perror( "fail read" );
                return -1;
            }
            printf("Read from pipe: %s\n", strReadPipe );

           if ( !strcmp( strReadPipe, EXIT_STR ) )
            {
                wait(NULL);
                break;
            }
        }

        close( pipeTest[0] );
    }
    else if ( pid == 0 )         //子进程, 从键盘获取字符串, 并写入pipe
    {
        close( pipeTest[0] );    //子进程只需要写管道, 所以关闭读管道
        char strGetBuf[MAX_INPUT_LEN];
        while ( 1 )
        {
            fgets( strGetBuf, sizeof(strGetBuf), stdin );
            strGetBuf[ strlen(strGetBuf) - 1 ] = '\0';  //将fgets获取的最后一个字符\n换为\0
            ssize_t iRetWrite = write( pipeTest[1], strGetBuf, strlen( strGetBuf ) + 1 );  // 将\0也写入pipe, 以方便处理
            if ( iRetWrite == -1 )
            {
                perror( "fail write" );
                return -1;
            }
            if ( !strcmp( strGetBuf, EXIT_STR ) )
            {
                break;
            }
        }
        close( pipeTest[1] );
    }
    else
    {
        perror( "fail fork" );
    }
    
    return 0;
}


/*

程序功能:
    两个进程通过pipe建立通信, 子进程从终端读取用户输入, 父进程打印用户输入字符串.
    如果用户输入"quit", 程序退出.

所涉及的主要函数:
    pipe
    fork
    fgets
    write
    read
    close

程序流程:

    pipe

    fork

    父进程
        关闭写通道
        while ( 读取pipe不为"quit" )
        {
            打印pipe中的字符串
        }
        关闭读通道
        wait回收子进程

    子进程
        关闭读通道
        while ( 1 )
        {
            从键盘获取字符串
            写入pipe
            如果字符串为"quit"
                退出循环
        }
        关闭写通道
        


*/